﻿#region [===== Using =====]
using System;
using System.Globalization;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
#endregion

namespace TPG.SharePoint.Workflow
{
    /// <summary>
    /// Provides a special implementation of an <see cref="TaskPage" />
    /// that allows specific placeholders on the page to be defined with 
    /// meta-data.
    /// </summary>
    /// <remarks>
    /// <para>The TaskFormHost is a special <see cref="TaskPage"/> 
    /// to allow specific placeholders of the ASPX page to be defined 
    /// using metadata. Depending on the section the placeholders can be filled
    /// with text or a UserControl. The placeholders 
    /// can be filled by metadata properties in the XML workflow 
    /// definition. The following table displays the placeholders and their 
    /// properties.</para>
    /// <list>
    ///     <listheader>Section</listheader>
    ///     <listheader>Description</listheader>
    ///     <listheader>Allowed Content</listheader>
    ///     <listheader>Required</listheader>
    /// </list>
    /// <para>Workflow tasks are identified using an integer ID. The 
    /// TaskFormHost uses this ID as the placeholder type for 
    /// all the placeholders contained on the page.
    /// &lt;Task_0_FormUrl&gt; is 
    /// as sample metadata property.</para>
    /// </remarks>
    public class TaskFormHost 
        : TaskPage, IWorkflowDataPage<TaskData>
    {
        #region [===== Instance fields =====]
        /// <summary>
        /// The placeholder for the page title.
        /// </summary>
        /// <remarks>
        /// The content displayed in the placeholder is determined dynamically
        /// using the workflow definition.
        /// </remarks>
        protected WorkflowControlPlaceHolder TitlePlaceHolder;
        /// <summary>
        /// The placeholder for the page header.
        /// </summary>
        /// <remarks>
        /// The content displayed in the placeholder is determined dynamically
        /// using the workflow definition.
        /// </remarks>
        protected WorkflowControlPlaceHolder HeaderPlaceHolder;
        /// <summary>
        /// The placeholder for the page descrviption.
        /// </summary>
        /// <remarks>
        /// The content displayed in the placeholder is determined dynamically
        /// using the workflow definition.
        /// </remarks>
        protected WorkflowControlPlaceHolder PageDescriptionPlaceHolder;
        /// <summary>
        /// The placeholder for the progress display.
        /// </summary>
        /// <remarks>
        /// The content displayed in the placeholder is determined dynamically
        /// using the workflow definition.
        /// </remarks>
        protected WorkflowControlPlaceHolder ProgressPlaceHolder;
        /// <summary>
        /// The placeholder for the main control.
        /// </summary>
        /// <remarks>
        /// The content displayed in the placeholder is determined dynamically
        /// using the workflow definition.
        /// </remarks>
        protected TaskControlPlaceHolder FormPlaceHolder;
        /// <summary>
        /// Indicates if the Page.Validate method has been called and if the 
        /// form should check Page.IsValid before submitting the workflow
        /// association.
        /// </summary>
        private bool _hasValidated;
        #endregion

        #region [===== Public methods =====]
        /// <summary>
        /// Ensures that this class only checks for valid pages when page 
        /// validation has actually occured.
        /// </summary>
        public override void Validate()
        {
            base.Validate();
            _hasValidated = true;
        }

        /// <summary>
        /// Ensures that this class only checks for valid pages when page 
        /// validation has actually occured.
        /// </summary>
        /// <param name="validationGroup">The group to validate.</param>
        public override void Validate(string validationGroup)
        {
            base.Validate(validationGroup);
            _hasValidated = true;
        }
        #endregion

        #region [===== IWorkflowDataPage explicit implementation =====]
        /// <summary>
        /// Gets the current data of the form as a 
        /// <see cref="TaskData"/> object.
        /// </summary>
        /// <returns>The current persisted task data.</returns>
        /// <remarks>
        /// This method has been explicitly implemented. The interface itself 
        /// is internal, so the only way host controls can get to the data is 
        /// through the structures defined by 
        /// <see cref="WorkflowDataControl&lt;TData, TMetaData&gt;" />.
        /// </remarks>
        TaskData IWorkflowDataPage<TaskData>.GetData()
        {
            return GetWorkflowTaskData();
        }
        #endregion

        #region [===== Protected methods =====]
        /// <summary>
        /// This method is for internal use only and should not be directly
        /// called from your code.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param> 
        protected void PlaceHolder_CreatingControl(object sender, EventArgs e)
        {
            WorkflowControlPlaceHolder placeHolder = sender as WorkflowControlPlaceHolder;
            int taskType = (int)base.ListItem[SPBuiltInFieldId.TaskType];
            placeHolder.PlaceHolderType = taskType.ToString(CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// Handles the common button commands.
        /// </summary>
        /// <param name="source">
        /// The control raising the bubbled event.
        /// </param>
        /// <param name="args">An EventArgs containing event data.</param>
        /// <returns><b>True</b> when the bubbled event has been handled,
        /// otherwise <b>false</b></returns>
        protected override bool OnBubbleEvent(object source, EventArgs args)
        {
            CommandEventArgs e = args as CommandEventArgs;
            if (e != null)
            {
                if (_hasValidated == false || IsValid)
                {
                    if (e.CommandName == "Cancel")
                        CancelTask();
                    else if (e.CommandName == "Commit")
                    {
                        WorkflowDataControl<TaskData, TaskMetaData> dataControl =
                            FormPlaceHolder.GetWorkflowControl();
                        CommitTask(dataControl.SaveData(e.CommandArgument));
                    }
                }
            }
            return base.OnBubbleEvent(source, args);
        }

        /// <summary>
        /// Gets the HTML to display in the progress screen.
        /// </summary>
        /// <remarks>
        /// By default this method renders the 
        /// <see cref="TaskFormHost.ProgressPlaceHolder"/> placeholder.
        /// </remarks>
        /// <returns>A string of HTML, without the HTML, 
        /// BODY or FORM tags</returns>
        protected override string GetProgressHtml()
        {
            return ProgressPlaceHolder.RenderAsHtml();
        }
        #endregion
    }
}
